package com.example.infrastructure.parser;

/**
 * @Author moyin
 * @Description TODO
 * @Date 2025/3/11 02:12
 * @Email 82400672@qq.com
 **/

import lombok.SneakyThrows;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PluginConfigDomParser {

    public static PluginConfigModel parse(InputStream xmlStream) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(xmlStream);
        Element root = doc.getDocumentElement();

        PluginConfigModel config = new PluginConfigModel();
        config.setVersion(getElementText(root, "version"));
        config.setId(getElementText(root, "id"));
        config.setName(getElementText(root, "name"));
        config.setIdeaVersion(parseIdeaVersion(root));
        config.setVendor(parseVendor(root));
        config.setDescription(getElementText(root, "description"));
        config.setDependencies(parseDependencies(root));
        config.setExtensionPoints(parseExtensionPoints(root));
        config.setExtensions(parseExtensions(root));

        return config;
    }

    // 解析 Vendor 节点
    private static PluginConfigModel.IdeaVersion parseIdeaVersion(Element root) {
        Element ideaVersionElement = (Element) root.getElementsByTagName("idea-version").item(0);
        if (ideaVersionElement == null) return null;

        PluginConfigModel.IdeaVersion ideaVersion = new PluginConfigModel.IdeaVersion();
        ideaVersion.setSinceBuild(ideaVersionElement.getAttribute("since-build"));
        ideaVersion.setUntilBuild(ideaVersionElement.getAttribute("until-build"));
        return ideaVersion;
    }

    // 解析 Vendor 节点
    private static PluginConfigModel.Vendor parseVendor(Element root) {
        Element vendorElement = (Element) root.getElementsByTagName("vendor").item(0);
        if (vendorElement == null) return null;

        PluginConfigModel.Vendor vendor = new PluginConfigModel.Vendor();
        vendor.setEmail(vendorElement.getAttribute("email"));
        vendor.setUrl(vendorElement.getAttribute("url"));
        vendor.setName(vendorElement.getTextContent().trim());
        return vendor;
    }

    // 解析依赖列表
    private static List<String> parseDependencies(Element root) {
        NodeList dependsNodes = root.getElementsByTagName("depends");
        List<String> dependencies = new ArrayList<>();
        for (int i = 0; i < dependsNodes.getLength(); i++) {
            dependencies.add(dependsNodes.item(i).getTextContent().trim());
        }
        return dependencies;
    }

    // 解析扩展点
    private static PluginConfigModel.ExtensionPoints parseExtensionPoints(Element root) {
        Element pointsElement = (Element) root.getElementsByTagName("extensionPoints").item(0);
        if (pointsElement == null) return null;

        PluginConfigModel.ExtensionPoints extensionPoints = new PluginConfigModel.ExtensionPoints();
        NodeList pointNodes = pointsElement.getElementsByTagName("extensionPoint");
        List<PluginConfigModel.ExtensionPoint> points = new ArrayList<>();

        for (int i = 0; i < pointNodes.getLength(); i++) {
            Element pointElement = (Element) pointNodes.item(i);
            PluginConfigModel.ExtensionPoint point = new PluginConfigModel.ExtensionPoint();
            point.setName(pointElement.getAttribute("name"));
            point.setInterfaceClass(pointElement.getAttribute("interface"));
            points.add(point);
        }

        extensionPoints.setPoints(points);
        return extensionPoints;
    }

    // 解析动态扩展内容
    private static Map<String, Object> parseExtensions(Element root) {
        Element extensionsElement = (Element) root.getElementsByTagName("extensions").item(0);
        if (extensionsElement == null) return null;

        NodeList dynamicNodes = extensionsElement.getChildNodes();
        List<Element> dynamicElements = new ArrayList<>();

        for (int i = 0; i < dynamicNodes.getLength(); i++) {
            if (dynamicNodes.item(i) instanceof Element) {
                dynamicElements.add((Element) dynamicNodes.item(i));
            }
        }

        return convertExtensionsToMap(dynamicElements);
    }

    public static Map<String, Object> convertExtensionsToMap(List<Element> dynamicElements) {
        Map<String, Object> resultMap = new HashMap<>();

        for (Element element : dynamicElements) {
            String nodeName = element.getNodeName();

            // Convert attributes to a map
            Map<String, String> attributes = new HashMap<>();
            for (int i = 0; i < element.getAttributes().getLength(); i++) {
                org.w3c.dom.Attr attr = (org.w3c.dom.Attr) element.getAttributes().item(i);
                attributes.put(attr.getName(), attr.getValue());
            }

            // If the element has no child nodes, treat it as a simple key-value pair
            if (element.getChildNodes().getLength() == 0) {
                resultMap.put(nodeName, attributes); // Store attributes as a map
            } else {
                // If the element has child nodes, recursively process them
                resultMap.put(nodeName, convertExtensionsToMap(List.of(element))); // Process child nodes
            }
        }

        return resultMap;
    }

    // 获取指定子节点的文本内容
    private static String getElementText(Element parent, String tagName) {
        NodeList nodes = parent.getElementsByTagName(tagName);
        return nodes.getLength() > 0 ? nodes.item(0).getTextContent().trim() : null;
    }

    @SneakyThrows
    public static void main(String[] args) {
        File pluginXmlFile = new File("/Users/moyin/Documents/code/gitee/qd/platform-service/extension-mapper/src/main/resources/files/plugin.xml");

        // 从类路径读取XML文件
        PluginConfigModel config = PluginConfigDomParser.parse(new FileInputStream(pluginXmlFile));

        // 打印关键字段验证
        System.out.println("ID: " + config.getId()); // com.kld.md.modelDesigner
        System.out.println("Vendor Email: " + config.getVendor().getEmail()); // 824000672@qq.com
        System.out.println("Dependencies: " + config.getDependencies()); // [com.intellij.modules.platform, ...]
        System.out.println("Extension Points: " + config.getExtensionPoints().getPoints().size()); // 2
        System.out.println("Dynamic Elements: " + config.getExtensions().size()); // 8
    }
}
